#ifndef _IPADDRESSIMPL_HPP_
#define _IPADDRESSIMPL_HPP_

#include "types.hpp"
#include "jhdefs.hpp"
#include "net/SocketDefs.hpp"
#include "stdlib/exception.hpp"
using namespace JHCPP::stdlib::jhException;

#include <string>

NET_NAMESPACE_BEGIN

class CIPAddressImpl
{
public:
	enum Family
	{
		IPv4
#ifdef JH_HAVE_IPv6
		,IPv6
#endif
	};

	virtual ~CIPAddressImpl();
	virtual CIPAddressImpl* clone() const = 0;
	virtual std::string toString() const = 0;
	virtual int length() const = 0;
	virtual const void* addr() const = 0;
	virtual Family family() const = 0;
	virtual int af() const = 0;
	virtual UInt32 scope() const = 0;
	virtual bool isWildcard() const	= 0;
	virtual bool isBroadcast() const = 0;
	virtual bool isLoopback() const = 0;
	virtual bool isMulticast() const = 0;
	virtual bool isLinkLocal() const = 0;
	virtual bool isSiteLocal() const = 0;
	virtual bool isIPv4Mapped() const = 0;
	virtual bool isIPv4Compatible() const = 0;
	virtual bool isWellKnownMC() const = 0;
	virtual bool isNodeLocalMC() const = 0;
	virtual bool isLinkLocalMC() const = 0;
	virtual bool isSiteLocalMC() const = 0;
	virtual bool isOrgLocalMC() const = 0;
	virtual bool isGlobalMC() const = 0;
	virtual void mask(const CIPAddressImpl* pMask, const CIPAddressImpl* pSet) = 0;
	virtual unsigned prefixLength() const = 0;

protected:
	CIPAddressImpl();

private:
	CIPAddressImpl(const CIPAddressImpl&);
	CIPAddressImpl& operator = (const CIPAddressImpl&);
};

//
// CIPv4AddressImpl
//
class CIPv4AddressImpl : public CIPAddressImpl
{
public:
	CIPv4AddressImpl();
	CIPv4AddressImpl(const void* addr);
	CIPv4AddressImpl(unsigned prefix);
	CIPv4AddressImpl(const CIPv4AddressImpl& addr);
	CIPv4AddressImpl& operator = (const CIPv4AddressImpl&);
	std::string toString() const;
	JH_SOCKETLEN length() const;
	const void* addr() const;
	Family family() const;
	int af() const;
	unsigned prefixLength() const;
	UInt32 scope() const;
	bool isWildcard() const;
	bool isBroadcast() const;
	bool isLoopback() const;
	bool isMulticast() const;
	bool isLinkLocal() const;
	bool isSiteLocal() const;
	bool isIPv4Compatible() const;
	bool isIPv4Mapped() const;
	bool isWellKnownMC() const;
	bool isNodeLocalMC() const;
	bool isLinkLocalMC() const;
	bool isSiteLocalMC() const;
	bool isOrgLocalMC() const;
	bool isGlobalMC() const;
	static CIPv4AddressImpl parse(const std::string& addr);
	void mask(const CIPAddressImpl* pMask, const CIPAddressImpl* pSet);
	CIPAddressImpl* clone() const;
	CIPv4AddressImpl operator & (const CIPv4AddressImpl& addr) const;
	CIPv4AddressImpl operator | (const CIPv4AddressImpl& addr) const;
	CIPv4AddressImpl operator ^ (const CIPv4AddressImpl& addr) const;
	CIPv4AddressImpl operator ~ () const;
	bool operator == (const CIPv4AddressImpl& addr) const;
	bool operator != (const CIPv4AddressImpl& addr) const;

private:	
	struct in_addr m_addr;
};

#ifdef JH_HAVE_IPv6
//
// CIPv6AddressImpl
//
class CIPv6AddressImpl : public CIPAddressImpl
{
public:
	CIPv6AddressImpl();
	CIPv6AddressImpl(const void* addr);
	CIPv6AddressImpl(const void* addr, UInt32 scope);
	CIPv6AddressImpl(unsigned prefix);
	std::string toString() const;
	JH_SOCKETLEN length() const;
	const void* addr() const;
	Family family() const;
	int af() const;
	unsigned prefixLength() const;
	UInt32 scope() const;
	bool isWildcard() const;
	bool isBroadcast() const;
	bool isLoopback() const;
	bool isMulticast() const;
	bool isLinkLocal() const;
	bool isSiteLocal() const;
	bool isIPv4Compatible() const;
	bool isIPv4Mapped() const;
	bool isWellKnownMC() const;
	bool isNodeLocalMC() const;
	bool isLinkLocalMC() const;
	bool isSiteLocalMC() const;
	bool isOrgLocalMC() const;
	bool isGlobalMC() const;
	static CIPv6AddressImpl parse(const std::string& addr);
	void mask(const CIPAddressImpl* pMask, const CIPAddressImpl* pSet);
	CIPAddressImpl* clone() const;
	CIPv6AddressImpl operator & (const CIPv6AddressImpl& addr) const;
	CIPv6AddressImpl operator | (const CIPv6AddressImpl& addr) const;
	CIPv6AddressImpl operator ^ (const CIPv6AddressImpl& addr) const;
	CIPv6AddressImpl operator ~ () const;
	bool operator == (const CIPv6AddressImpl& addr) const;
	bool operator != (const CIPv6AddressImpl& addr) const;
	CIPv6AddressImpl(const CIPv6AddressImpl& addr);
	CIPv6AddressImpl& operator = (const CIPv6AddressImpl&);

private:
	struct in6_addr m_addr;
	unsigned int    m_scope;
};
#endif

NET_NAMESPACE_END

#endif
